﻿using System;
using System.Collections.Generic;
using System.Text;

namespace BitTicTacToe
{
    class Field
    {
        private uint _field = 0;

        // Метод хода.
        public void Move(int position, bool isCross)
        {
            // Если ходит крестик, то пара битов равна 01, а если нолик - 10. И дальше - сдвижение и запись на нужную позицию.
            uint mask = (uint)(isCross ? 1 : 2);
            mask <<= (position * 2);

            _field |= mask;
        }
        
        // Метод проверки, есть ли победитель, по индексу последнего хода.
        public bool Check(int lastIndex, bool isCross)
        {
            if (lastIndex < 0 || lastIndex > 8)
            {
                return false;
            }

            // Определяем uint значение поля битов, где заполненной является одна конкретная линия.
            // Например, значение поля, где верхняя горизонтальная линия заполнена крестиками, равно ...010101, что в виде uint равно 21.

            uint line = 0;

            // Горизонтальные линии.
            if (lastIndex == 0 || lastIndex == 1 || lastIndex == 2)
            {
                line = (uint)(isCross ? 21 : 42);
            }
            else if (lastIndex == 3 || lastIndex == 4 || lastIndex == 5)
            {
                line = (uint)(isCross ? 1344 : 2688);
            }
            else if (lastIndex == 6 || lastIndex == 7 || lastIndex == 8)
            {
                line = (uint)(isCross ? 86016 : 172032);
            }

            // Проверка.
            if (CheckLine(line))
            {
                return true;
            }

            // Вертикальные линии.
            if (lastIndex == 0 || lastIndex == 3 || lastIndex == 6)
            {
                line = (uint)(isCross ? 4161 : 8322);
            }
            else if (lastIndex == 1 || lastIndex == 4 || lastIndex == 7)
            {
                line = (uint)(isCross ? 16644 : 33288);
            }
            else if (lastIndex == 2 || lastIndex == 5 || lastIndex == 8)
            {
                line = (uint)(isCross ? 66576 : 133152);
            }

            // Проверка.
            if (CheckLine(line))
            {
                return true;
            }

            // Диагональные линии.
            if (lastIndex == 0 || lastIndex == 4 || lastIndex == 8)
            {
                line = (uint)(isCross ? 65793 : 131586);
            }
            else if (lastIndex == 2 || lastIndex == 4 || lastIndex == 6)
            {
                line = (uint)(isCross ? 4368 : 8736);
            }

            // Проверка.
            if (CheckLine(line))
            {
                return true;
            }

            return false;
        }

        // Вынесенный в отдельный метод блок кода из функции Check(int lastIndex, bool isCross).
        private bool CheckLine(uint line)
        {
            uint difference = _field ^ line;
            if (difference + line == _field)
            {
                return true;
            }

            return false;
        }

        // Очистка поля.
        public void Clear()
        {
            _field = 0;
        }
    }
}
